package com.gzc.just.play.last.war.common.share.data.impl;

import com.gzc.just.play.last.war.common.share.data.DataAccessService;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * SQLite数据访问服务实现
 * 为All-in-One开发模式提供SQLite数据库支持
 */
@Service
@Transactional
public class SQLiteDataAccessService implements DataAccessService {
    
    private static final Logger logger = LoggerFactory.getLogger(SQLiteDataAccessService.class);
    
    @PersistenceContext
    private EntityManager entityManager;
    
    @Override
    public <T, ID extends Serializable> Optional<T> findById(Class<T> entityClass, ID id) {
        try {
            T entity = entityManager.find(entityClass, id);
            return Optional.ofNullable(entity);
        } catch (Exception e) {
            logger.error("根据ID查找实体失败: entityClass={}, id={}", entityClass.getSimpleName(), id, e);
            return Optional.empty();
        }
    }
    
    @Override
    public <T> T save(T entity) {
        try {
            if (entityManager.contains(entity)) {
                return entityManager.merge(entity);
            } else {
                entityManager.persist(entity);
                entityManager.flush(); // 确保ID生成
                return entity;
            }
        } catch (Exception e) {
            logger.error("保存实体失败: entity={}", entity, e);
            throw new RuntimeException("保存实体失败", e);
        }
    }
    
    @Override
    public <T> List<T> saveAll(Iterable<T> entities) {
        try {
            List<T> savedEntities = new java.util.ArrayList<>();
            for (T entity : entities) {
                savedEntities.add(save(entity));
            }
            return savedEntities;
        } catch (Exception e) {
            logger.error("批量保存实体失败", e);
            throw new RuntimeException("批量保存实体失败", e);
        }
    }
    
    @Override
    public <T> void delete(T entity) {
        try {
            entityManager.remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
        } catch (Exception e) {
            logger.error("删除实体失败: entity={}", entity, e);
            throw new RuntimeException("删除实体失败", e);
        }
    }
    
    @Override
    public <ID extends Serializable> void deleteById(Class<?> entityClass, ID id) {
        try {
            Object entity = entityManager.find(entityClass, id);
            if (entity != null) {
                entityManager.remove(entity);
            }
        } catch (Exception e) {
            logger.error("根据ID删除实体失败: entityClass={}, id={}", entityClass.getSimpleName(), id, e);
            throw new RuntimeException("根据ID删除实体失败", e);
        }
    }
    
    @Override
    public <T> List<T> findAll(Class<T> entityClass) {
        try {
            String jpql = "SELECT e FROM " + entityClass.getSimpleName() + " e";
            TypedQuery<T> query = entityManager.createQuery(jpql, entityClass);
            return query.getResultList();
        } catch (Exception e) {
            logger.error("查询所有实体失败: entityClass={}", entityClass.getSimpleName(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public <T> Page<T> findAll(Class<T> entityClass, Pageable pageable) {
        try {
            // 查询总数
            String countJpql = "SELECT COUNT(e) FROM " + entityClass.getSimpleName() + " e";
            Query countQuery = entityManager.createQuery(countJpql);
            long total = (Long) countQuery.getSingleResult();
            
            // 查询数据
            String jpql = "SELECT e FROM " + entityClass.getSimpleName() + " e";
            TypedQuery<T> query = entityManager.createQuery(jpql, entityClass);
            query.setFirstResult((int) pageable.getOffset());
            query.setMaxResults(pageable.getPageSize());
            
            List<T> content = query.getResultList();
            
            return new PageImpl<>(content, pageable, total);
        } catch (Exception e) {
            logger.error("分页查询实体失败: entityClass={}", entityClass.getSimpleName(), e);
            return new PageImpl<>(Collections.emptyList());
        }
    }
    
    @Override
    public <T, ID extends Serializable> List<T> findAllById(Class<T> entityClass, Iterable<ID> ids) {
        try {
            if (!ids.iterator().hasNext()) {
                return Collections.emptyList();
            }
            
            String jpql = "SELECT e FROM " + entityClass.getSimpleName() + " e WHERE e.id IN :ids";
            TypedQuery<T> query = entityManager.createQuery(jpql, entityClass);
            query.setParameter("ids", ids);
            
            return query.getResultList();
        } catch (Exception e) {
            logger.error("根据ID列表查询实体失败: entityClass={}", entityClass.getSimpleName(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public <T, ID extends Serializable> boolean existsById(Class<T> entityClass, ID id) {
        try {
            String jpql = "SELECT COUNT(e) > 0 FROM " + entityClass.getSimpleName() + " e WHERE e.id = :id";
            Query query = entityManager.createQuery(jpql);
            query.setParameter("id", id);
            
            return (Boolean) query.getSingleResult();
        } catch (Exception e) {
            logger.error("判断实体是否存在失败: entityClass={}, id={}", entityClass.getSimpleName(), id, e);
            return false;
        }
    }
    
    @Override
    public <T> long count(Class<T> entityClass) {
        try {
            String jpql = "SELECT COUNT(e) FROM " + entityClass.getSimpleName() + " e";
            Query query = entityManager.createQuery(jpql);
            
            return (Long) query.getSingleResult();
        } catch (Exception e) {
            logger.error("统计实体数量失败: entityClass={}", entityClass.getSimpleName(), e);
            return 0;
        }
    }
    
    @Override
    public <T> List<T> executeQuery(String query, Class<T> resultClass, Object... params) {
        try {
            TypedQuery<T> jpaQuery = entityManager.createQuery(query, resultClass);
            
            for (int i = 0; i < params.length; i++) {
                jpaQuery.setParameter(i + 1, params[i]);
            }
            
            return jpaQuery.getResultList();
        } catch (Exception e) {
            logger.error("执行自定义查询失败: query={}", query, e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public int executeUpdate(String updateQuery, Object... params) {
        try {
            Query query = entityManager.createQuery(updateQuery);
            
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i + 1, params[i]);
            }
            
            return query.executeUpdate();
        } catch (Exception e) {
            logger.error("执行自定义更新失败: updateQuery={}", updateQuery, e);
            throw new RuntimeException("执行自定义更新失败", e);
        }
    }
    
    @Override
    public void beginTransaction() {
        // JPA会自动管理事务，此方法仅用于兼容接口
        logger.debug("开始事务（SQLite自动管理）");
    }
    
    @Override
    public void commitTransaction() {
        // JPA会自动管理事务，此方法仅用于兼容接口
        logger.debug("提交事务（SQLite自动管理）");
    }
    
    @Override
    public void rollbackTransaction() {
        // JPA会自动管理事务，此方法仅用于兼容接口
        logger.debug("回滚事务（SQLite自动管理）");
    }
    
    @Override
    public <T> T executeInTransaction(TransactionalOperation<T> operation) {
        try {
            return operation.execute();
        } catch (Exception e) {
            logger.error("事务执行失败", e);
            throw new RuntimeException("事务执行失败", e);
        }
    }
    
    @Override
    public DatabaseType getDatabaseType() {
        return DatabaseType.SQLITE;
    }
}